home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1990 Commodore-Amiga, Inc. All rights reserved
- */
-
- /*
- * WatchMan. Watches files for changes. Example Appshell application
- */
-
- #include <libraries/appshell.h>
- #include <clib/appshell_protos.h>
-
- #include "fn_handler.h"
- #include "wm.h"
-
- extern LONG _stack = 4000;
- extern UBYTE *_procname = APPNAME;
- extern LONG _priority = 0;
- extern LONG _BackGroundIO = 0;
- extern LONG _Backstdout;
-
- struct FilePart {
- struct PoolHeader *ph;
- struct List *filelist;
- struct List *flaglist;
- LONG Retries;
- LONG Interval;
- LONG Flags;
- UBYTE FlagDesc[12];
- UBYTE Filename[512];
- };
-
- UBYTE *flagdescr[] =
- {
- "FN_CREATED",
- "FN_DELETED",
- "FN_SMALLER",
- "FN_BIGGER",
- "FN_NEWER",
- "FN_MUSTEXIST",
- };
-
- extern struct WBStartup *WBenchMsg;
-
- VOID
- main(int argc, char **argv)
- {
-
- if (_Backstdout) {
- Close(_Backstdout);
- _Backstdout = 0;
- }
- HandleApp(argc, argv, WBenchMsg, WM);
- }
-
- /* Custom application init. Setup local lists etc. */
- VOID
- WMInitFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp;
- struct Node *node;
- LONG w, g;
- int i;
-
- if (fp = AllocVec(sizeof(struct FilePart), MEMF_CLEAR)) {
- if (fp->ph = CreatePrivatePool(MEMF_CLEAR, 2048, 128)) {
- fp->filelist = AllocPooled(sizeof(struct List), fp->ph);
- fp->flaglist = AllocPooled(sizeof(struct List), fp->ph);
- NewList(fp->filelist);
- NewList(fp->flaglist);
-
- /* Fill in the list for available flags */
- for (i = 0; i < 6; i++) {
- node = AllocPooled(sizeof(struct Node), fp->ph);
- node->ln_Name = AllocPooled(strlen(flagdescr[i]) + 1, fp->ph);
- strcpy(node->ln_Name, flagdescr[i]);
- AddTail(fp->flaglist, node);
- }
- /* And update the listview gadget */
- if (APSHGetGadgetInfo(ai, "MAIN", "FLAGLIST", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, fp->flaglist,
- GTLV_Top, 0,
- TAG_DONE);
-
- }
- /* Use ai->ai_UserData to pass structure around */
- ai->ai_UserData = fp;
- } else {
- FreeVec(fp);
- }
- }
- }
-
- /* Custom application exit, free resources */
- VOID
- WMExitFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
-
- struct FilePart *fp;
- struct Node *wnode, *nnode;
-
- if (ai->ai_UserData) {
- /* Get pointer to application structure */
- fp = (struct FilePart *) ai->ai_UserData;
- if (fp->ph) {
- /* Free the lists and free the pool. */
- wnode = (struct Node *) fp->filelist->lh_Head;
- while (nnode = (struct Node *) (wnode->ln_Succ)) {
- FreePooled(wnode->ln_Name, fp->ph);
- Remove(wnode);
- FreePooled(wnode, fp->ph);
- wnode = nnode;
- }
- FreePooled(fp->filelist, fp->ph);
- wnode = (struct Node *) fp->flaglist->lh_Head;
- while (nnode = (struct Node *) (wnode->ln_Succ)) {
- FreePooled(wnode->ln_Name, fp->ph);
- Remove(wnode);
- FreePooled(wnode, fp->ph);
- wnode = nnode;
- }
- FreePooled(fp->flaglist, fp->ph);
- DeletePrivatePool(fp->ph);
- }
- FreeVec(fp);
- }
- }
-
- VOID
- WMAboutFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- STRPTR buffer;
-
- /*
- * Simple fill a buffer and call NotifyUser() to put up a nice requester.
- */
- if (buffer = AllocPooled(512, fp->ph)) {
- sprintf(buffer, "%s\n\n%s\n\n%s",
- ai->ai_AppVersion,
- ai->ai_AppCopyright,
- ai->ai_AppAuthor);
-
- NotifyUser(ai, buffer, NULL);
- FreePooled(buffer, fp->ph);
- }
- }
-
- /* Application function called by fn_handler */
- VOID
- FileNotification(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FNData *fndata;
- struct FilePart *fp = (struct FilePart *) ai->ai_UserData;
- struct Node *node;
- ULONG w, g;
- UBYTE *buffer;
-
- /*
- * When the handler calls us, it passes the pointer to the relevant data
- * as tag data
- */
-
- fndata = (struct FNData *) GetTagData(APSH_CmdData, NULL, tl);
-
- /* Fill in a buffer and put up a cool requester */
- buffer = AllocPooled(300, fp->ph);
- sprintf(buffer, "File Notification!\n\nTarget: %s\nStatus: %s%s%s%s%s%s",
- fndata->fnd_Filename,
- (fndata->fnd_Status & FN_DONE) ? "DONE " : NULL,
- (fndata->fnd_Status & FN_CREATED) ? "CREATED " : NULL,
- (fndata->fnd_Status & FN_DELETED) ? "DELETED " : NULL,
- (fndata->fnd_Status & FN_SMALLER) ? "SMALLER " : NULL,
- (fndata->fnd_Status & FN_BIGGER) ? "BIGGER " : NULL,
- (fndata->fnd_Status & FN_NEWER) ? "NEWER" : NULL);
-
- NotifyUser(ai, buffer, NULL);
- FreePooled(buffer, fp->ph);
-
- /*
- * If the handler tells us the number of retries for the target has been
- * reached, try to remove the target from the list and listview gadget.
- * If the window is hidden, we cannot touch the gadget, so we'll leave a
- * false entry. That will be dealt with when the user tries to re-delete
- * the target
- */
-
- if (fndata->fnd_Status & FN_DONE) {
- if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
- /*
- * Detach the list from the listview gadget, so we can update the
- * list
- */
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, ~0,
- TAG_DONE);
-
- /* If it's there, remove it */
- if (node = FindName(fp->filelist, fp->Filename)) {
- FreePooled(node->ln_Name, fp->ph);
- Remove(node);
- FreePooled(node, fp->ph);
- }
- /* And attach the list to the listview gadget again */
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, fp->filelist,
- GTLV_Top, 0,
- TAG_DONE);
- }
- }
- }
-
-
- void
- SetFilenameFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- struct Gadget *gadget;
- struct WBArg *wbarg;
- STRPTR buffer = NULL;
- STRPTR entry;
- STRPTR parsedline;
- STRPTR argv[MAXARG];
- ULONG argc = 0;
- ULONG w, g;
-
- if (str) {
- parsedline = BuildParseLine(str, &argc, argv);
- }
- if (argc >= 2) {
- /* We're called with a string argument, via AREXX or cmdshell */
- entry = argv[1];
- if (APSHGetGadgetInfo(ai, "MAIN", "FSTRING", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTST_String, entry,
- TAG_DONE);
- }
- } else {
- gadget = (struct Gadget *) GetTagData(APSH_MsgIAddress, NULL, tl);
- if (gadget)
- entry = ((STRPTR) ((struct StringInfo *) (gadget)->SpecialInfo)->Buffer);
- else {
- /* WB drop support */
- wbarg = (struct WBArg *) GetTagData(APSH_WBArg, NULL, tl);
- buffer = AllocPooled(512, fp->ph);
- /*
- * WB passes a lock to the directory and a pointer to the
- * filename which was dropped.
- */
- if (NameFromLock(wbarg->wa_Lock, buffer, 512)) {
- entry = wbarg->wa_Name;
- if (AddPart(buffer, entry, 512))
- entry = buffer;
- } else
- entry = NULL;
- if (APSHGetGadgetInfo(ai, "MAIN", "FSTRING", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTST_String, entry,
- TAG_DONE);
- }
- }
-
- /* Activate next gadget, it seems logical */
- if (APSHGetGadgetInfo(ai, "MAIN", "ISTRING", &w, &g))
- ActivateGadget((struct Gadget *) g, (struct Window *) w, NULL);
- }
- strcpy(fp->Filename, entry);
- if (buffer)
- FreePooled(buffer, fp->ph);
- if (str)
- FreeParseLine(parsedline);
- }
-
-
- void
- SetRetriesFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- struct Gadget *gadget;
- LONG retries;
- STRPTR parsedline;
- STRPTR argv[MAXARG];
- ULONG argc;
- ULONG w, g;
-
- if (str) {
- parsedline = BuildParseLine(str, &argc, argv);
- }
- if (argc >= 2) {
- stcd_l(argv[1], &retries);
- if (APSHGetGadgetInfo(ai, "MAIN", "RSTRING", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTIN_Number, retries,
- TAG_DONE);
- }
- } else {
- gadget = (struct Gadget *) GetTagData(APSH_MsgIAddress, NULL, tl);
- retries = ((LONG) ((struct StringInfo *) (gadget)->SpecialInfo)->LongInt);
- }
- fp->Retries = retries;
- if (str)
- FreeParseLine(parsedline);
- }
-
-
- void
- SetIntervalFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- struct Gadget *gadget;
- LONG interval;
- STRPTR argv[MAXARG];
- STRPTR parsedline;
- ULONG argc = 0;
- ULONG w, g;
-
- if (str) {
- parsedline = BuildParseLine(str, &argc, argv);
- }
- if (argc >= 2) {
- stcd_l(argv[1], &interval);
- if (APSHGetGadgetInfo(ai, "MAIN", "ISTRING", &w, &g)) {
- /*
- * Currently GadTools doesn't allow signed numbers, so negatives
- * come out 'weird'.
- */
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTIN_Number, interval,
- TAG_DONE);
- }
- } else {
- gadget = (struct Gadget *) GetTagData(APSH_MsgIAddress, NULL, tl);
- interval = ((LONG) ((struct StringInfo *) (gadget)->SpecialInfo)->LongInt);
- /* Activate next gadget, it seems logical */
- if (APSHGetGadgetInfo(ai, "MAIN", "RSTRING", &w, &g))
- ActivateGadget((struct Gadget *) g, (struct Window *) w, NULL);
- }
- fp->Interval = interval;
- if (str)
- FreeParseLine(parsedline);
- }
-
-
- void
- SetFlagsFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
-
- struct FilePart *fp = ai->ai_UserData;
- USHORT code;
- STRPTR parsedline;
- ULONG argc;
- STRPTR argv[MAXARG];
- ULONG w, g;
-
- if (str)
- parsedline = BuildParseLine(str, &argc, argv);
- if (argc >= 2) {
- /* We're called with a string argment, like
- * "setflags fn_newer|fn_mustexist"
- */
- if (MatchValue(argv[1], "FN_MUSTEXIST"))
- fp->Flags ^= FN_MUSTEXIST;
- if (MatchValue(argv[1], "FN_CREATED"))
- fp->Flags ^= FN_CREATED;
- if (MatchValue(argv[1], "FN_DELETED"))
- fp->Flags ^= FN_DELETED;
- if (MatchValue(argv[1], "FN_SMALLER"))
- fp->Flags ^= FN_SMALLER;
- if (MatchValue(argv[1], "FN_BIGGER"))
- fp->Flags ^= FN_BIGGER;
- if (MatchValue(argv[1], "FN_NEWER"))
- fp->Flags ^= FN_NEWER;
- } else {
- /* Tags then? */
- code = (USHORT) GetTagData(APSH_MsgCode, 10, tl);
-
- switch (code) {
- case 0:
- fp->Flags ^= FN_CREATED;
- break;
- case 1:
- fp->Flags ^= FN_DELETED;
- break;
- case 2:
- fp->Flags ^= FN_SMALLER;
- break;
- case 3:
- fp->Flags ^= FN_BIGGER;
- break;
- case 4:
- fp->Flags ^= FN_NEWER;
- break;
- case 5:
- fp->Flags ^= FN_MUSTEXIST;
- break;
- default:
- break;
- }
- }
-
- /* Put the flag letters in a fixed buffer and show it, if possible */
- sprintf(fp->FlagDesc, "%s%s%s%s%s%s",
- (fp->Flags & FN_CREATED) ? "C " : NULL,
- (fp->Flags & FN_DELETED) ? "D " : NULL,
- (fp->Flags & FN_SMALLER) ? "S " : NULL,
- (fp->Flags & FN_BIGGER) ? "B " : NULL,
- (fp->Flags & FN_NEWER) ? "N " : NULL,
- (fp->Flags & FN_MUSTEXIST) ? "M" : NULL);
-
- if (APSHGetGadgetInfo(ai, "MAIN", "SHOWTEXT", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTTX_Text, fp->FlagDesc,
- TAG_DONE);
- }
- if (str)
- FreeParseLine(parsedline);
- }
-
- /* Accept the choice in the 'target' listview as general filename */
- void
- GetFileFromListFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- struct Node *node;
- USHORT code;
- ULONG w, g;
- int i;
-
- code = GetTagData(APSH_MsgCode, 0, tl);
-
- if (code != 32) {
- /* Actually selected a target */
- node = fp->filelist->lh_Head;
- for (i = 0; i < code; i++)
- node = node->ln_Succ;
-
- /* Make choice general target */
- strcpy(fp->Filename, node->ln_Name);
-
- /* Update the filename string gadget, if possible */
- if (APSHGetGadgetInfo(ai, "MAIN", "FSTRING", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTST_String, fp->Filename,
- TAG_DONE);
- }
- }
- }
-
- /* Put in a request to the handler to add a target */
- VOID
- AddTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- struct Node *node;
- ULONG w, g;
- BOOL error = 0;
-
- /* Call the handler function, because it's called with all
- * tags (even if they're NULL) we don't actually use the
- * handlers defaults.
- */
-
- FileNotify(ai, NULL,
- FN_Command, FN_ADDTARGET,
- FN_Filename, fp->Filename,
- FN_Interval, fp->Interval,
- FN_Retries, fp->Retries,
- FN_Flags, fp->Flags,
- FN_Error, &error,
- TAG_DONE);
-
- if (error == 0) {
- /* Handler accepted the request, try to make it visible */
- if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
- /* Detach the list from the listview gadget, so it can
- * be updated.
- */
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, ~0,
- TAG_DONE);
-
- /* If it's not there already, add a new node */
- if (!(node = FindName(fp->filelist, fp->Filename))) {
- node = AllocPooled(sizeof(struct Node), fp->ph);
- node->ln_Name = AllocPooled(strlen(fp->Filename) + 1, fp->ph);
- strcpy(node->ln_Name, fp->Filename);
- AddTail(fp->filelist, node);
- }
- /* And attach the list to the listview gadget again */
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, fp->filelist,
- GTLV_Top, 0,
- TAG_DONE);
- }
- }
- }
-
-
- /* Put in a request to the handler to stop watching a target */
- VOID
- DelTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- struct Node *node;
- ULONG w, g;
- BOOL error;
-
- /* Call handler function with the target name which should be
- * removed from the list */
- FileNotify(ai, NULL,
- FN_Command, FN_DELTARGET,
- FN_Filename, fp->Filename,
- FN_Error, &error,
- TAG_DONE);
-
- /* Even if the handler doesn't know the target and complains,
- * remove it from the list, the user doesn't want it anymore.
- */
-
- /* Detach the list from the listview gadget, so it can be updated */
- if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, ~0,
- TAG_DONE);
-
- /* Remove the node from the list if it's found */
- if (node = FindName(fp->filelist, fp->Filename)) {
- FreePooled(node->ln_Name, fp->ph);
- Remove(node);
- FreePooled(node, fp->ph);
- }
- /* Attach the list to the listview gadget again */
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, fp->filelist,
- GTLV_Top, 0,
- TAG_DONE);
- }
- }
-
-
- /* Put in a request to sync a target */
- VOID
- SyncTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
-
- struct FilePart *fp = ai->ai_UserData;
- struct Node *node;
- ULONG w, g;
- BOOL error;
-
- /* Call the handler function */
- FileNotify(ai, NULL,
- FN_Command, FN_SYNC,
- FN_Filename, fp->Filename,
- FN_Error, &error,
- TAG_DONE);
-
- /*
- * If sync failed, try to remove it from the list. It's probably removed
- * thru the shell or arexx.
- */
-
- if (error) {
- /* Detach list from the listview gadget so it can be updated */
- if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, ~0,
- TAG_DONE);
-
- /* Remove node from the list if found */
- if (node = FindName(fp->filelist, fp->Filename)) {
- FreePooled(node->ln_Name, fp->ph);
- Remove(node);
- FreePooled(node, fp->ph);
- }
- /* Attach list to the listview gadget again */
- GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
- GTLV_Labels, fp->filelist,
- GTLV_Top, 0,
- TAG_DONE);
- }
- }
- }
-
- VOID
- InquiryTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
- {
- struct FilePart *fp = ai->ai_UserData;
- struct FNData *fndata;
- BOOL error;
- STRPTR buffer;
-
- fndata = AllocPooled(sizeof(struct FNData), fp->ph);
-
- FileNotify(ai, NULL,
- FN_Command, FN_INQUIRY,
- FN_Filename, fp->Filename,
- FN_Error, &error,
- FN_Buffer, fndata,
- TAG_DONE);
-
- if (!(error)) {
- buffer = AllocPooled(300, fp->ph);
- sprintf(buffer, "Target: %s\nInterval: %ld\nRetries: %ld\nFlags: %s%s%s%s%s%s",
- fndata->fnd_Filename,
- fndata->fnd_Interval,
- fndata->fnd_Retries,
- (fndata->fnd_Flags & FN_CREATED) ? "FN_CREATED " : NULL,
- (fndata->fnd_Flags & FN_DELETED) ? "FN_DELETED " : NULL,
- (fndata->fnd_Flags & FN_SMALLER) ? "FN_SMALLER " : NULL,
- (fndata->fnd_Flags & FN_BIGGER) ? "FN_BIGGER " : NULL,
- (fndata->fnd_Flags & FN_NEWER) ? "FN_NEWER " : NULL,
- (fndata->fnd_Flags & FN_MUSTEXIST) ? "FN_MUSTEXIST " : NULL);
-
- NotifyUser(ai, buffer, NULL);
- FreePooled(buffer, fp->ph);
- }
- FreePooled(fndata, fp->ph);
- }
-